const socket = require("socket.io")
const { decode  } = require("../utils/jwt")
const Messages = require("../models/messageModel")
const User = require("../models/userModel")

module.exports = (server) => {
    // 接收一个服务器实例，升级为 websocket 连接
    const io = socket(server, {
        cors: {
            origin: "http://localhost:3000",
            credentials: true
        }
    })

    // 检查用户连接，是否带有 token
    io.use(async (socket, next) => {
        try {
            const token = socket.handshake.auth.token;
            if (!token) {
                return next(new Error("invalid token"));
            }
            const { id: userId } = await decode(token);
            socket.userId = userId;
            next();  // 成功时调用 next
        } catch (err) {
            next(new Error("invalid token"));
        }
    });
    
    // 前端连接后，会触发 connection 并发送一个 socket 过来
    // 这个socket和前端的socket 是同一个，都可以控制该连接的建立与断开

    // 1. 出现登录冲突时，向客户端发送冲突信息
    // 2. 检查用户是否已经登录，如果已经登录，则踢下线'
    let users = new Map()
    io.on("connection", async(socket) => {
        const oldSocketId = users.get(socket.userId)
        if (oldSocketId) {
            // io.sockets 是一个 Map，key 是 socketId，value 是 socket 实例
            io.to(oldSocketId).emit("conflict", socket.userId)
            io.sockets.sockets.get(oldSocketId).disconnect()
            socket.broadcast.emit("offline", socket.userId)
        }
        // 添加新连接信息
        users.set(socket.userId, socket.id)

        console.log("有新的连接", users)

        // 获取所有联系人
        let contacts = await User.find().lean();
        contacts = contacts.filter(item => item._id != socket.userId)
 
        // 向自己发送用户列表
        socket.emit("users", Object.fromEntries(users.entries()), contacts)

        // 向其他用户广播用户列表
        socket.broadcast.emit("online", socket.userId)

        // 发送私人消息
        socket.on("private_message", async (data) => {
            const { to, from, content, type } = data

            // 1. 首先保存到数据库
            const result = await Messages.create({
                message: {
                    content,
                    type
                },
                userIds: [to, from],
                senderId: from,
            })

            // 2. 然后发送给接收者
            const toSocketId = users.get(to)
            console.log(toSocketId, "接收者")
            if (toSocketId) {
                io.to(toSocketId).emit("private_message", result)
            }
        })

        socket.on("chats", async (chatId, callback) => {
            console.log(socket.userId,chatId, "请求聊天记录")
            const result = await Messages.find({userIds: {$all: [chatId, socket.userId]}}).sort({updateAt: 1})
            callback(result)
        })

        // 断开连接
        socket.on("disconnect", () => {
            users.delete(socket.userId)
            console.log("用户断开连接", users)
            socket.broadcast.emit("offline", socket.userId)
        })
    })

    return io
}